# Неизменяемые значения

В чистом функциональном программировании используются только неизменяемые значения. В Scala это означает: 

- все переменные создаются как поля `val`
- используются только неизменяемые классы коллекций, такие как `List`, `Vector` и неизменяемые классы `Map` и `Set`

Использование только неизменяемых переменных поднимает интересный вопрос: 
если все статично, как вообще что-то меняется?

Когда дело доходит до использования коллекций, один из ответов заключается в том, 
что существующая коллекция не меняется; 
вместо этого функция применяется к коллекции, чтобы создать новую. 
Именно здесь вступают в действие функции высшего порядка, такие как `map` и `filter`.

Например, представим, что есть список имен в нижнем регистре — `List[String]`, 
и необходимо найти все имена, начинающиеся с буквы `"j"`, чтобы затем сделать первые буквы заглавными. 
В ФП код будет выглядеть так:

```dotty
val a = List("jane", "jon", "mary", "joe")
// a: List[String] = List("jane", "jon", "mary", "joe")
val b = a.filter(_.startsWith("j")).map(_.capitalize)
// b: List[String] = List("Jane", "Jon", "Joe")
```

Как показано, исходный список `a` не меняется. 
Вместо этого к `a` применяется функция фильтрации и преобразования, чтобы создать новую коллекцию, 
и результат присваивается неизменяемой переменной `b`.

Точно так же в ФП не используются классы с изменяемыми параметрами конструктора `var`. 
В ФП создание такого класса не привествуется:

```dotty
class Person(var firstName: String, var lastName: String)
```

Вместо этого обычно создаются `case class`-ы, чьи параметры конструктора по умолчанию неизменяемые (`val`):

```dotty
case class Person(firstName: String, lastName: String)
```

Теперь можно создать экземпляр `Person` как поле `val`:

```dotty
val reginald = Person("Reginald", "Dwight")
// reginald: Person = Person(firstName = "Reginald", lastName = "Dwight")
```

Затем, при необходимости внести изменения в данные, используется метод `copy`, 
который поставляется с `case class`-ом, чтобы "обновлять данные через создание копии", например:

```dotty
val elton = reginald.copy(
  firstName = "Elton",   
  lastName = "John"      
)
// elton: Person = Person(firstName = "Elton", lastName = "John")
```

Существуют множество других приёмов работы с неизменяемыми коллекциями и переменными.

> В зависимости от задач вместо `case class`-ов можно создавать `enum`-ы, `trait`-ы или классы. 
> Для более подробной информации См. главу ["Моделирование данных"](../modeling.md).


---

**Ссылки:**

- [Scala3 book](https://docs.scala-lang.org/scala3/book/fp-immutable-values.html)
